# $Id: util.py 7557b5d4d82b 2012/12/02 09:07:16 pgurumur $
# Copyright (c) 2009 Prabhu Gurumurthy  <pgurumur@gmail.com>
# 
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

import os
import threading
import warnings

from djanet.db import netdb, ssndb
from djanet.lib import ip, stdlib, sshlib
from djanet.lib.exception import AppError

class IPv6(object):
   def __init__(self, Address):
      self._address = None
      self._length = 0

      if Address:
         self._address = Address
         self._length = self._address.length

      self._conflict = None

   def _checkparent(self):
      retval = True
      for ix in netdb.Ipblock.objects.filter(
            prefix__lte = self._length, version = 6).all():
         print ix
         if self._address in ix.ip:
            self._conflict = ix.ip
            retval = False
            break

      if retval:
         for ix in ssndb.Ipv6Prefix.objects.using('ssn').all():
            if ix.ip.length < self._length:
               if self._address in ix.ip:
                  self._conflict = ix.ip
                  retval = False
                  break

      return retval

   def _checkchild(self):
      retval = True
      for ix in netdb.Ipblock.objects.filter(prefix__gt = self._length,
            version = 6).all():
         if ix.ip in self._address:
            self._conflict  = ix.ip
            retval = False
            break

      if retval:
         for ix in ssndb.Ipv6Prefix.objects.using('ssn').all():
            if ix.ip.length > self._length:
               if ix.ip in self._address:
                  self._conflict = ix.ip
                  retval = False
                  break

      return retval

   def _checkpeer(self):
      retval = True
      temp = netdb.Ipblock.objects.filter(address = int(self._address),
            version = 6).values()
      if len(temp):
         self._conflict = self._address
         retval = False

      if retval:
         temp = ssndb.Ipv6Prefix.objects.using('ssn').filter(
               prefix = str(self._address)).values()
         if len(temp):
            self._conflict = self._address
            retval = False

      return retval

   def ValidIPv6(self):
      return bool(
            self._checkparent() and self._checkchild() and self._checkpeer())

   conflict = property(fget = lambda self: self._conflict)

class ssh(dict):
   def __init__(self, *args, **kwargs):
      super(ssh, self).__init__(*args, **kwargs)
      self.update(*args, **kwargs)
      self._client = None
      self._log = log.StreamLog(stdlib.my_name(self))

   def __getattr__(self, key):
      retval = None
      if "key" in self:
         retval = self[key]

      return retval

   def __nonzero__(self):
      flag = False
      if hasattr(self, "username") and hasattr(self, "password") and hasattr(
            self, "hostname"):
         flag = True

      return flag

   def error(self, fmt, *args):
      self.close()
      raise AppError(stdlib.sprintf(fmt, *args))

   def start(self):
      flag = False
      filename = None
      if hasattr(self, "filename"):
         if os.path.exists(self["filename"]):
            filename = self["filename"]
            flag = True

      try:
         if self and flag and not self._client:
            with sshlib.SSHClient(host = self["hostname"],
                  user = self["username"], passwd = self["password"],
                  port = 22, verbose = self["verbose"]) as self._client:
               self._client.Connect()
               if self._client.Auth(bool(self["password"])):
                  self._client.GetChannel(exfile = filename)
               else:
                  self.error("cannot authenticate to %s", self["hostname"])
      except exception.SSHException as err:
         self.error(err.message)
      finally:
         self.close()

   def close(self):
      if self._client:
         try:
            self._client.close()
         except:
            pass
         finally:
            self._client = None

class ConfigPush(threading.Thread):
   def __init__(self, SSHObject = None, Name = None, Verbose = False):
      super(ConfigPush, self).__init__(name = Name, verbose = Verbose)
      self._log = log.StreamLog(stdlib.my_name(self))
      self._ssh = None

      if isinstance(SSHObject, dict) and SSHObject:
         self._ssh = SSHObject

   def warn(self, fmt, *args):
      mesg = stdlib.sprintf(fmt, *args)
      self._log(mesg)
      warnings.warn(mesg)

   def run(self):
      try:
         self._ssh.start()
      except AppError as err:
         self.warn(err.message)
      else:
         self._ssh.close()
